package cc

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"ez/config/code"
	"gitee.com/dreamwood/ez-go/ez"
	"gitee.com/dreamwood/ez-go/tools"
	"net/http"
	"strconv"
	"strings"
)

type MySession struct {
	Session   *ez.Session
	HttpQuery *ez.HttpQuery
}

func New(session *ez.Session) *MySession {
	return &MySession{
		Session:   session,
		HttpQuery: ez.NewHttpQuery(),
	}
}

func (this *MySession) Get(key string) *ez.InputAnyThing {
	return this.Session.Input.Get(key)
}

func (this *MySession) GetId() int64 {
	return this.Session.Input.Get("id").IsInt64(0)
}

func (this *MySession) GetHeader() http.Header {
	return this.Session.Input.Request.Header
}

func (this *MySession) SetHeader(key string, value string) {
	this.Session.Input.Request.Header.Set(key, value)
}

func (this *MySession) CreateContext() context.Context {
	return context.WithValue(context.Background(), "MySession", this)
}

func (this *MySession) GetAuthToken() string {
	return this.Session.GetHeader().Get(ez.ConfigApi.AuthTokenName)
}

func (this *MySession) FillJson(model interface{}) error {
	return json.Unmarshal(this.Session.Input.Json, model)
}

func (this *MySession) CheckError(err error) bool {
	if err != nil {
		data := NewJsonOut(code.ErrorServer, err.Error())
		this.Session.Output.Json(data)
		return true
	}
	return false
}

// 如果不好理解就使用这个别名
func (this *MySession) HasError(err error) bool { return this.CheckError(err) }

func (this *MySession) Try(err error) bool { return this.CheckError(err) }

func (this *MySession) JsonOut(data interface{}) {
	this.Session.Output.Json(data)
}
func (this *MySession) Html(data string) {
	this.Session.Output.Html(data)
}

func (this *MySession) ReturnSuccess(message string, data interface{}) {
	jsonData := make(map[string]interface{})
	jsonData["code"] = code.Success
	jsonData["message"] = message
	jsonData["data"] = data
	this.JsonOut(jsonData)
}

func (this *MySession) ReturnError(code int, message string, data interface{}) {
	jsonData := make(map[string]interface{})
	jsonData["code"] = code
	jsonData["message"] = message
	jsonData["data"] = data
	this.JsonOut(jsonData)
}

func (this *MySession) Stop() {
	this.Session.IsStop = true
}

// Handler
func (this *MySession) StopHandle() {
	this.Session.Handler.IsStop = true
}

func (this *MySession) LogToSession(title string, data interface{}) {
	content, _ := json.Marshal(data)
	this.Session.AddSessionLog("UserLog", title, string(content), "G")
}

type JsonOut struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data"`
}

func NewJsonOut(p ...interface{}) *JsonOut {
	jsonOut := new(JsonOut)
	if len(p) > 0 {
		jsonOut.Code = p[0].(int)
	}
	if len(p) > 1 {
		jsonOut.Message = p[1].(string)
	}
	if len(p) > 2 {
		jsonOut.Data = p[2]
	}
	return jsonOut
}

func (this *MySession) GetHttpQuery() *ez.HttpQuery {
	query := ez.NewHttpQuery()
	if ez.Try(this.FillJson(query)) {
		this.HttpQuery = query
		return query
	}
	this.HttpQuery = query
	return query
}

/**
剥离出公共的用户方法
*/

func (this *MySession) GetUserId() int64 {
	uid, _, _ := DecodeUserToken(GetTokenFromRequest(this.Session.Input.Request))
	return uid
}

func (this *MySession) GetUserRoles(session *ez.Session) []int64 {
	_, _, roles := DecodeUserToken(GetTokenFromRequest(session.Input.Request))
	return roles
}

func DecodeUserToken(token string) (uid int64, timestamp int64, roles []int64) {
	if token == "" {
		return
	}
	if data, err := base64.StdEncoding.DecodeString(token); err == nil {
		originData := tools.AesDecrypt(string(data), ez.ConfigCore.Vi)
		if strings.Contains(originData, "\n") {
			originDataArr := strings.Split(originData, "\n")
			if len(originDataArr) == 3 {
				uidd, _ := strconv.Atoi(originDataArr[0])
				uid = int64(uidd)
				ts, _ := strconv.Atoi(originDataArr[1])
				if ts > 0 {
					timestamp = int64(ts)
				}
				rolesStr := strings.Split(originDataArr[2], " ")
				for _, role := range rolesStr {
					roleInt, _ := strconv.Atoi(role)
					roles = append(roles, int64(roleInt))
				}
			}
		}
	}
	return
}

func GetTokenFromRequest(request *http.Request) string {
	token := request.Header.Get(ez.ConfigApi.AuthTokenName)
	return token
}

func GetUidFromCtx(ctx context.Context) int64 {
	if ctx == nil {
		return 0
	}
	session := ez.GetSessionFromContext(ctx)
	if session == nil {
		return 0
	}
	uid, _, _ := DecodeUserToken(GetTokenFromRequest(session.Input.Request))
	return uid
}
